home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / nuf210.arc / NUFIND.C < prev    next >
Text File  |  1990-06-14  |  15KB  |  491 lines

  1. /*----------------------------------------------------------------------*/
  2. /*    NUFIND.EXE - Enhanced MS DOS implementation of the Unix find
  3.  *                  command.  NUFIND will find all files matching a set
  4.  *                  of specified criteria and perform any of several
  5.  *                  operations (move, copy, delete, etc.) on each file
  6.  *                  that matches the search criteria.
  7.  *
  8.  *     Version:    2.1.0
  9.  *     Date:        June 13, 1990
  10.  *     Author:        Don A. Williams
  11.  *
  12.             *********************  NOTICE  ************************
  13.             *  Contrary to the current trend in MS-DOS  software  *
  14.             *  this  program,  for whatever it is worth,  is NOT  *
  15.             *  copyrighted (with the exception  of  the  runtime  *
  16.             *  library  from  the C compiler)!  The program,  in  *
  17.             *  whole or in part,  may  be  used  freely  in  any  *
  18.             *  fashion or environment desired.  If you find this  *
  19.             *  program  to  be  useful  to you,  do NOT send any  *
  20.             *  contribution to the author;  in the words of Rick  *
  21.             *  Conn,   'Enjoy!'   However,   if   you  make  any  *
  22.             *  improvements,  I would enjoy receiving a copy  of  *
  23.             *  the  modified source.  I can be reached,  usually  *
  24.             *  within 24  hours,  by  messages  on  any  of  the  *
  25.             *  following Phoenix, AZ systems (the Phoenix systems *
  26.             *  can all be reached through StarLink node #9532):   *
  27.             *                                                     *
  28.             *     The Tool Shop BBS       [PCBOARD] [PC-Pursuit]  *
  29.             *         (602) 279-2673   1200/2400/9600 bps         *
  30.             *     Technoids Anonymous     [PCBOARD]               *
  31.             *         (602) 899-4876   300/1200/2400 bps          *
  32.             *         (602) 899-5233                              *
  33.             *         (602) 786-9131                              *
  34.             *     Inn On The Park         [PCBOARD]               *
  35.             *         (602) 957-0631   1200/2400/9600 bps         *
  36.             *     Pascalaholics Anonymous [WBBS]                  *
  37.             *         (602) 484-9356   1200/2400 bps              *
  38.             *                                                     *
  39.             *  or:                                                *
  40.             *     Blue Ridge Express     [RBBS] Richmond, VA      *
  41.             *         (804) 790-1675   2400 bps [StarLink #413]   *
  42.             *                                                     *
  43.             *     The Lunacy BBS         [PCBOARD] Van Nuys, CA   *
  44.             *         (805) 251-7052   2400/9600 [StarLink 6295]  *
  45.             *         (805) 251-8637   2400/9600 [StarLink 6295]  *
  46.             *                                                     *
  47.             *  or:                                                *
  48.             *     GEnie, mail address: DON-WILL                   *
  49.             *     CompuServ:           75410,543                  *
  50.             *                                                     *
  51.             *  Every  effort  has  been  made to avoid error and  *
  52.             *  moderately extensive testing has  been  performed  *
  53.             *  on  this  program,  however,  the author does not  *
  54.             *  warrant it to be fit for any  purpose  or  to  be  *
  55.             *  free  from  error and disclaims any liability for  *
  56.             *  actual or any other damage arising from  the  use  *
  57.             *  of this program.                                   *
  58.             *******************************************************
  59. */
  60.  
  61. #include <stdio.h>
  62. #include <string.h>
  63. #include <stdlib.h>
  64. #include <ctype.h>
  65. #include <conio.h>
  66. #include <dir.h>
  67. #include <dos.h>
  68. #include <io.h>
  69. #include <sys\stat.h>
  70.  
  71. #include "nufind.h"
  72. #include "queue.h"
  73.  
  74. struct DateSel {
  75.     unsigned Date;
  76.     int      Swt;
  77.     };
  78.  
  79. QUE_DEF Paths, ExcPaths, IncNameQueue, ExcNameQueue;
  80. QUE_DEF IncPathQueue, ExcPathQueue, NoCreateQ;
  81. char ProgName[9];
  82. char CurDir[66] = "";
  83. char DestDir[66] = "";
  84. char *CommandString;
  85. int BaseLength   = 0;
  86. long TotalSize   = 0L;
  87.  
  88. int RecurSwt   = 1;
  89. int PrtSwt     = 1;
  90. int LsSwt      = 0;
  91. int LdSwt      = 0;
  92. int RmSwt      = 0;
  93. int RmDirSwt   = 0;
  94. int RmSwtA     = 0;
  95. int AttrSwt    = 0;
  96. int NotAttrSwt = 0;
  97. int AttrOnSwt  = 0;
  98. int AttrOffSwt = 0;
  99. int CopySwt    = 0;
  100. int MoveSwt    = 0;
  101. int TreeSwt    = 0;
  102. int SizeSwt    = 0;
  103. int ExecSwt    = 0;
  104. int SumSwt     = 0;
  105. int RelSwt     = 0;
  106. int OldDate       = 0;
  107.  
  108. struct DateSel Since  = {0, 0};
  109. struct DateSel Before = {0, 0};
  110.  
  111. char AttrMask    = 0;
  112. char NotAttrMask = 0;
  113. char AttrOnMask  = 0;
  114. char AttrOffMask = 0;
  115. long Size        = 0;
  116.  
  117. char *ExistRef        = NULL;
  118. char *NotExistRef    = NULL;
  119. char *CompRef        = NULL;
  120. char *NotCompRef    = NULL;
  121. INFO_BLOCK *LT_Ref        = NULL;
  122. INFO_BLOCK *LE_Ref        = NULL;
  123. INFO_BLOCK *GT_Ref        = NULL;
  124. INFO_BLOCK *GE_Ref        = NULL;
  125. INFO_BLOCK *LT_DateRef    = NULL;
  126. INFO_BLOCK *LE_DateRef    = NULL;
  127. INFO_BLOCK *GT_DateRef    = NULL;
  128. INFO_BLOCK *GE_DateRef    = NULL;
  129.  
  130. struct date Today;
  131.  
  132. unsigned TodayDate;
  133.  
  134.  
  135. void GetProgName (char *Name, char *argv);
  136. char *RootPath (char *CurDir, char *RelPath, char *FullPath);
  137. void GetCurrentDisk (int *CurDisk);
  138. int  GetCurrentDirectory (int Disk, char *CurDir);
  139. void GetArgs (char *argv[], int i);
  140. void QueuePath (QUE_DEF *Q, char *Name);
  141. void ProcessPaths (char *Name, int Level);
  142. int  Select (INFO_BLOCK *Name);
  143. void Action (INFO_BLOCK *Name);
  144. char *PrintNumber (long Number);
  145. void Replace (char *Str1, int n, char *Str2);
  146. void ErrorMsg (char *Format, ...);
  147. void ExceptionMsg (char *Format, ...);
  148. void ErrorExit (char *Format, ...);
  149. void GetPath (QUE_DEF *Q, char *Arg);
  150.  
  151. char P_Name[70];
  152.  
  153.  void
  154. main (int argc, char *argv[]) {
  155.     int i;
  156.     int CurDisk;
  157.     QUE_ENTRY *t;
  158.  
  159.     GetProgName(ProgName, argv[0]);
  160.     fprintf(stderr, "%s: NewUFind - Version %s: Date - %s\n", ProgName,
  161.             VERSION, VER_DATE);
  162.  
  163.     getdate(&Today);
  164.     TodayDate = ( (Today.da_year - 1980) << 9) | (Today.da_mon << 5) | Today.da_day;
  165.     GetCurrentDisk(&CurDisk);
  166.     CurDir[0] = (char) (CurDisk + 'A'); CurDir[1] = ':'; CurDir[2] = '\\';
  167.     GetCurrentDirectory(0, CurDir+3);
  168.     strlwr(CurDir);
  169.     if (CurDir[strlen(CurDir)-1] != '\\') strcat(CurDir, "\\");
  170.     InitQueue(&Paths); InitQueue(&IncNameQueue); InitQueue(&ExcNameQueue);
  171.     InitQueue(&IncPathQueue); InitQueue(&ExcPathQueue);
  172.     InitQueue(&NoCreateQ);
  173.  
  174.     for (i=1; i < argc && argv[i][0] != '-'; ++i) GetPath(&Paths, argv[i]);
  175.  
  176.     GetArgs(argv, i);
  177.  
  178.     if (Paths.Count == 0)
  179.         if ( (Enque(&Paths, CurDir)) == NULL)
  180.             ErrorExit("Insufficient memory for Path list.\n");
  181.     for (t=Paths.Head; t != NULL; t = t->Next) ProcessPaths(t->Body, 0);
  182.  
  183.     if (SumSwt) printf("Total Size = %16s\n", PrintNumber(TotalSize));
  184.     }
  185.  
  186.  
  187.  void
  188. QueuePath (QUE_DEF *Q, char *Name) {
  189.     char FullPath[66];
  190.  
  191.     if (RootPath(CurDir, Name, FullPath) != NULL) {
  192.         if (FullPath[strlen(FullPath)-1] != '\\') strcat(FullPath, "\\");
  193.         if ( (Enque(Q, FullPath)) == NULL)
  194.             ErrorExit("Insufficient memory for Path list.\n");
  195.         }
  196.     }
  197.  
  198.  void
  199. ProcessPaths (char *Body, int Level) {
  200.     QUE_DEF *Dirs;
  201.     QUE_ENTRY *u, *v;
  202.     char Name[66], DirName[66];
  203.     struct ffblk DirBlk;
  204.     int Status, i;
  205.     INFO_BLOCK FileInfo;
  206.  
  207.     for (u=ExcPaths.Head; u != NULL; u = u->Next)
  208.         if (!strcmp(Body, u->Body)) return;
  209.     if (!Level) BaseLength = strlen(Body);
  210.     if ( (Dirs = malloc(sizeof(QUE_DEF))) == NULL) {
  211.         ErrorMsg("Insufficient memory for directory list.\n");
  212.         return;
  213.         }
  214.     InitQueue(Dirs);
  215.     strcpy(Name, Body);
  216.     DirName[0] = '\0';
  217.     if ( (i = strlen(Name)) > 3 && Name[i-2] != ':' && Name[i-1] == '\\')
  218.         Name[i-1] = '\0';
  219.     if (Name[i-1] != '\\' && (Status = findfirst(Name, &DirBlk, 0xFF)) != 0)
  220.         return;
  221.  
  222.     if ( Name[i-1] == '\\' || (DirBlk.ff_attrib & FA_DIREC) != 0 ) {
  223.         strcpy(DirName, Name);
  224.         if (Name[i-1] != '\\') strcat(Name, "\\");
  225.         strcat(Name, "*.*");
  226.         Status = findfirst(Name, &DirBlk, 0xFF);
  227.         while (Status == 0) {
  228.             strcpy(FileInfo.Name, Body);
  229.             strcat(FileInfo.Name, DirBlk.ff_name);
  230.             strlwr(FileInfo.Name);
  231.             FileInfo.Attrib = DirBlk.ff_attrib;
  232.             FileInfo.FTime.Time =   DirBlk.ff_ftime;
  233.             FileInfo.FDate.Date =   DirBlk.ff_fdate;
  234.             FileInfo.Size =   DirBlk.ff_fsize;
  235.             if ( (DirBlk.ff_attrib & FA_DIREC) != 0 ) {
  236.                 if (!strcmp(DirBlk.ff_name, "..")
  237.                     || !strcmp(DirBlk.ff_name, ".") ) {
  238.                     Status = findnext(&DirBlk);
  239.                     continue;
  240.                     }
  241.                 strcpy(Name, Body); strcat(Name, DirBlk.ff_name);
  242.                 if ( (Enque(Dirs, Name)) == NULL) {
  243.                     ErrorMsg("Insufficient memory for directory list.\n");
  244.                     return;
  245.                     }
  246.                 if (Select(&FileInfo)) Action(&FileInfo);
  247.                 }
  248.             else if ( (DirBlk.ff_attrib & FA_LABEL) != 0 );
  249.             else if (Select(&FileInfo)) Action(&FileInfo);
  250.             Status = findnext(&DirBlk);
  251.             }
  252.         if (RecurSwt && Dirs->Count != 0) {
  253.             u = Dirs->Head;
  254.             while (u != NULL) {
  255.                 strcpy(Name, u->Body); strcat(Name, "\\");
  256.                 strlwr(Name);
  257.                 ProcessPaths(Name, Level + 1);
  258.                 free(u->Body);
  259.                 v = u->Next;
  260.                 free(u);
  261.                 u = v;
  262.                 }
  263.             InitQueue(Dirs);
  264.             }
  265.         }
  266.     else {
  267.         strcpy(FileInfo.Name, Name);
  268.         FileInfo.Attrib = DirBlk.ff_attrib;
  269.         FileInfo.FTime.Time   = DirBlk.ff_ftime;
  270.         FileInfo.FDate.Date   = DirBlk.ff_fdate;
  271.         FileInfo.Size   = DirBlk.ff_fsize;
  272.         if (Select(&FileInfo)) Action(&FileInfo);
  273.         }
  274.     if (RmDirSwt && DirName[0] != '\0' ) {
  275.         if (DirName[strlen(DirName)-2] == ':') return;
  276.         printf("RMDIR: %s\n", DirName);
  277.         CurDir[strlen(CurDir)-1] = '\0';
  278.         if (!strcmp(DirName, CurDir)) {
  279.             *(strrchr(CurDir, '\\')) = '\0';
  280.             chdir(CurDir);
  281.             }
  282.         strcat(CurDir, "\\");
  283.         if (rmdir(DirName)) perror("    FAILED");
  284.         }
  285.     }
  286.  
  287.  
  288.  void
  289. GetProgName (char *Name, char *argv) {
  290.     char *p, *p1;
  291.  
  292.     if ( (p = strrchr(argv, '\\')) != NULL) ++p;
  293.     else p = argv;
  294.     if ( (p1 = strchr(p, '.')) != NULL) *p1 = '\0';
  295.     strcpy(Name, p);
  296.     }
  297.  
  298.  
  299. /****************************************************************************
  300. * PrintNumber -- Print a long number, inserting ","s where needed.
  301. ****************************************************************************/
  302. char *
  303. PrintNumber (long Number) {
  304.     static char Temp[20];
  305.     int l, i;
  306.  
  307.     sprintf(Temp, "%lu", Number);
  308.     l = strlen(Temp);
  309.     for (i=0; i < l; ++i) {
  310.         if ( i && ((i) % 3) == 0) {
  311.             memmove(&Temp[l-i+1], &Temp[l-i], strlen(&Temp[l-i])+1);
  312.             Temp[l-i] = ',';
  313.             }
  314.         }
  315.     return(Temp);
  316.     }
  317.  
  318.  void
  319. ErrorExit (char *Format, ...) {
  320.     va_list ArgPtr;
  321.     extern char ProgName[];
  322.     extern int errno;
  323.  
  324.     fprintf(stderr, "%s: ", ProgName);
  325.     va_start(ArgPtr, Format);
  326.     vfprintf(stderr, Format, ArgPtr);
  327.     va_end(ArgPtr);
  328.     if (errno) perror("    ");
  329.     fprintf(stderr, "\n");
  330.     exit(1);
  331.     }
  332.  
  333.  
  334.  void
  335. Execute (char *Name) {
  336.     extern char *CommandString;
  337.  
  338.     char *Command, Dir[65], FName[9];
  339.     char *q, *p1, *p2;
  340.     int n;
  341.  
  342.     if ( (Command = malloc(129)) == NULL) {
  343.         ErrorMsg("Insufficient memory for command.\n");
  344.         return;
  345.         }
  346.     strcpy(Command, CommandString);
  347.     n = 0;
  348.     while ( (q = strchr(&Command[n], '%')) != NULL ) {
  349.         switch(toupper(*(q+1))) {
  350.             case 'F':
  351.                 p1 = strrchr(Name, '\\');
  352.                 Replace(q, 2, ++p1);
  353.                 break;
  354.             case 'P':
  355.                 Replace(q, 2, Name);
  356.                 break;
  357.             case 'N':
  358.                 p1 = strrchr(Name, '\\');
  359.                 p2 = strchr(++p1, '.');
  360.                 strncpy(FName, p1, (int) (p2 - p1) );
  361.                 FName[(int) (p2 - p1)] = '\0';
  362.                 Replace(q, 2, FName);
  363.                 break;
  364.             case 'E':
  365.                 p1 = strrchr(Name, '.');
  366.                 Replace(q, 2, ++p1);
  367.                 break;
  368.             case 'D':
  369.                 p1 = strrchr(Name, '\\');
  370.                 strncpy(Dir, Name, (int) (p1 - Name) );
  371.                 Dir[(int) (p1 - Name)] = '\0';
  372.                 Replace(q, 2, Dir);
  373.                 break;
  374.             }
  375.         n = (int) (q - Command) + 2;
  376.         }
  377.     system(Command);
  378.     free(Command);
  379.     }
  380.  
  381.  
  382. /**************************************************************************
  383.  * Replace - Replaces a number of characters equal to the length of Str2
  384.  *             in Str1 with the contents of Str2.  The position is Str1 is
  385.  *             specified by n.
  386.  *************************************************************************/
  387.  void
  388. Replace (char *Str1, int n, char *Str2) {
  389.     int    l, r;
  390.  
  391.     l = strlen(Str1);
  392.     r = strlen(Str2);
  393.     memmove(&Str1[r], &Str1[n], l - n + 1);
  394.     strncpy(Str1, Str2, r);
  395.     }
  396.  
  397.  
  398.  void
  399. ErrorMsg (char *Format, ...) {
  400.     va_list ArgPtr;
  401.     extern char ProgName[];
  402.     extern int errno;
  403.  
  404.     fprintf(stderr, "%s: - ", ProgName);
  405.     va_start(ArgPtr, Format);
  406.     vfprintf(stderr, Format, ArgPtr);
  407.     va_end(ArgPtr);
  408.     if (errno) perror("    ");
  409.     fprintf(stderr, "\n");
  410.     }
  411.  
  412.  
  413.  void
  414. ExceptionMsg (char *Format, ...) {
  415.     va_list ArgPtr;
  416.  
  417.     fprintf(stderr, "    ");
  418.     va_start(ArgPtr, Format);
  419.     vprintf(Format, ArgPtr);
  420.     va_end(ArgPtr);
  421.     fputc('\n', stdout);
  422.     if (errno) {
  423.         perror("      ");
  424.         fputc('\n', stdout);
  425.         }
  426.     }
  427.  
  428.  int
  429. GetYorN (char *Message, ...) {
  430.     va_list ArgPtr;
  431.     char Reply;
  432.  
  433.     while (1) {
  434.         va_start(ArgPtr, Message);
  435.         fprintf(stderr, "    ");
  436.         vfprintf(stderr, Message, ArgPtr);
  437.         fprintf(stderr, "('Y', 'N' or A)bort)? ");
  438.         Reply = toupper(getch());
  439.         if (Reply == 'A') exit(1);
  440.         if (Reply == 'Y' || Reply == 'N') break;
  441.         fprintf(stderr, "%c is invalid.\n \007", Reply);
  442.         }
  443.     va_end(ArgPtr);
  444.     fprintf(stderr, "%c\n", Reply);
  445.     return( (Reply == 'Y') );
  446.     }
  447.  
  448.  void
  449. GetPath (QUE_DEF *Q, char *Arg) {
  450.     extern char P_Name[70];
  451.  
  452.     char *p, Temp[65];
  453.     int i, j;
  454.  
  455.     CurDir[strlen(CurDir)-1] = '\0';
  456.     if ( !strcmp(Arg, ".") ) strcpy(P_Name, CurDir);
  457.     else if ( !strcmp(Arg, "..") ) {
  458.         p = strrchr(CurDir, '\\');
  459.         *p = '\0';
  460.         strcpy(P_Name, CurDir);
  461.         *p = '\\';
  462.         }
  463.     else strcpy(P_Name, Arg);
  464.     strcat(CurDir, "\\");
  465.     if ( (p = strchr(P_Name, ':')) != NULL) {
  466.         if ( (i = (int) (p - P_Name) ) > 1) {
  467.             for (j=0; j < i; ++j) {
  468.                 Temp[0] = P_Name[j];
  469.                 Temp[1] = '\0';
  470.                 strcat(Temp, p);
  471.                 if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  472.                 if (Enque(Q, Temp) == NULL)
  473.                     ErrorExit("Insufficient memory for Path List.\n");
  474.                 }
  475.             }
  476.         else {
  477.             strcpy(Temp, P_Name);
  478.             if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  479.             if (Enque(Q, Temp) == NULL)
  480.                 ErrorExit("Insufficient memory for Path List.\n");
  481.             }
  482.         }
  483.     else {
  484.         Temp[0] = CurDir[0]; Temp[1] = ':'; Temp[2] = '\0';
  485.         strcat(Temp, P_Name);
  486.         if (Temp[strlen(Temp)-1] != '\\') strcat(Temp, "\\");
  487.         if (Enque(Q, Temp) == NULL)
  488.             ErrorExit("Insufficient memory for Path List.\n");
  489.         }
  490.     }
  491.